package com.hzdesk.media.koreabatchmatvector.custom;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;

import com.hzdesk.media.koreabatchmatvector.R;
import com.hzdesk.media.koreabatchmatvector.base.MyClientApplication;
import com.hzdesk.media.koreabatchmatvector.bean.PathBean;
import com.hzdesk.media.koreabatchmatvector.config.AppConfig;
import com.hzdesk.media.koreabatchmatvector.contral.BitmapCtl;
import com.hzdesk.media.koreabatchmatvector.contral.BitmapUtil;
import com.hzdesk.media.koreabatchmatvector.contral.Circlectl;
import com.hzdesk.media.koreabatchmatvector.contral.CommonDef;
import com.hzdesk.media.koreabatchmatvector.contral.EraserCtl;
import com.hzdesk.media.koreabatchmatvector.contral.LineCtl;
import com.hzdesk.media.koreabatchmatvector.contral.OvaluCtl;
import com.hzdesk.media.koreabatchmatvector.contral.PenuCtl;
import com.hzdesk.media.koreabatchmatvector.contral.PlygonCtl;
import com.hzdesk.media.koreabatchmatvector.contral.RectuCtl;
import com.hzdesk.media.koreabatchmatvector.contral.Spraygun;
import com.hzdesk.media.koreabatchmatvector.inter.ISketchpadDraw;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;


/**
 * function :实现图形的绘制与显示
 *
 * @author Mr.Lee
 */
public class SketchpadView extends View {
    //设置画笔常量
    public static final int STROKE_PEN = 12;       //画笔1
    public static final int STROKE_ERASER = 2;    //橡皮擦2
    public static final int STROKE_PLYGON = 10;   //多边形3
    public static final int STROKE_RECT = 9;      //矩形 4
    public static final int STROKE_CIRCLE = 8;    //圆 5
    public static final int STROKE_OVAL = 7;      //椭圆 6
    public static final int STROKE_LINE = 6;      //直线7
    public static final int STROKE_SPRAYGUN = 5;      //喷枪8
    public static final int STROKE_PAINTPOT = 4;     //油漆桶9
    public static int flag = 0;                    //油漆桶参数

    public static final int UNDO_SIZE = 100;       //撤销栈的大小
    public static final int BITMAP_WIDTH = 650;        //画布高
    public static final int BITMAP_HEIGHT = 400;    //画布宽
    public static final int PAINT_COLOR_BULE = Color.BLUE;
    public static final int PAINT_COLOR_RED = Color.RED;
    public static final int PAINT_COLOR_BLACK = Color.BLACK;
    public static final int PAINT_COLOR_GREEN = Color.GREEN;
    public static final int PAINT_COLOR_YELLOW = Color.YELLOW;
    public static final int PAINT_COLOR_PURPLE = R.color.purple;
    public static int brush = 0;

    private int m_strokeType = STROKE_PEN;   //画笔风格
    private static String m_strokeColor = "FF0000";   //画笔颜色
    private static int m_penSize = CommonDef.SMALL_PEN_WIDTH;         //画笔大小
    private static int m_eraserSize = CommonDef.LARGE_ERASER_WIDTH;   //橡皮擦大小


    //实例新画布
    private boolean m_isEnableDraw = true;   //标记是否可以画
    private boolean m_isDirty = false;     //标记
    private boolean m_isTouchUp = false;    //标记是否鼠标弹起
    private boolean m_isSetForeBmp = false;   //标记是否设置了前bitmap
    private int m_bkColor = Color.TRANSPARENT;    //背景色

    private int m_canvasWidth = 100;    //画布宽
    private int m_canvasHeight = 100;    //画布高
    private boolean m_canClear = true;   //标记是否可清除

    private Bitmap m_foreBitmap = null;     //用于显示的bitmap
    private Bitmap m_tempForeBitmap = null; //用于缓冲的bitmap
    private Bitmap m_bkBitmap = null;       //用于背后画的bitmap

    private Canvas m_canvas;     //画布
    private Paint m_bitmapPaint = null;   //画笔
    private SketchPadUndoStack m_undoStack = null;//栈存放执行的操作
    private ISketchpadDraw m_curTool = null;   //记录操作的对象画笔类
    private List<SketchPadUndoStack> padUndoStacksList; // 存放栈集合

    private int num = 0;

    int antiontemp = 0;//获取鼠标点击画布的event
    boolean myLoop = false;// 喷枪结束标识符
    private Bitmap bgBitmap = null;
    private Context mContext;

    ///////////////// paint and Bk//////////////////////////////
    public void setContext(Context context) {
        mContext = context;
    }


    //画布参数设计
    public boolean isDirty() {
        return m_isDirty;   //
    }

    public void setDrawStrokeEnable(boolean isEnable) {
        m_isEnableDraw = isEnable;  //确定是否可绘图
    }

    public void setBkColor(int color) {   //设置背景颜色
        if (m_bkColor != color) {
            m_bkColor = color;
            invalidate();
        }
    }

    public static void setStrokeSize(int size, int type) {   //设置画笔的大小和橡皮擦大小
        switch (type) {
            case STROKE_PEN:
                m_penSize = size;
                break;

            case STROKE_ERASER:
                m_eraserSize = size;
                break;
        }
    }

    public static void setStrokeColor(String color) {   //设置画笔颜色
        m_strokeColor = color;
    }

    public static int getStrokeSize() {   //得到画笔的大小
        return m_penSize;
    }

    public static int getEraser() {   //得到橡皮擦的大小
        return m_eraserSize;
    }

    public static String getStrokeColor() {   //得到画笔的大小
        return m_strokeColor;
    }

    ////////////////////////////////////////////////////////////
    public void clearAllStrokes(int num) {   //清空设置
        if (m_canClear) {
            // 清空撤销栈
            m_undoStack.clearAllP();
            if (MyClientApplication.getUserNum() == 1 && num == 1) {
                for (int i = 0; i < padUndoStacksList.size(); i++) {
                    padUndoStacksList.get(i).clearAllP();
                    if (null != m_tempForeBitmap) {
                        m_tempForeBitmap.recycle();
                        m_tempForeBitmap = null;
                    }
                    // Create a new fore bitmap and set to canvas.
                    createStrokeBitmap(m_canvasWidth, m_canvasHeight);
                    invalidate();
                    m_isDirty = true;
                    m_canClear = false;
                }

                if (MyClientApplication.isRecording()) {
                    MyClientApplication.setmPathBeanList(new PathBean(new Date().getTime() - MyClientApplication.getStartTime(), AppConfig.PAINT_CLEAR, MyClientApplication.getUserNum()));
                }
            } else {
                //Toast.makeText(mApp, R.string.no_permissions, Toast.LENGTH_SHORT).show();
                for (Pair<Integer, ISketchpadDraw> pair : padUndoStacksList.get(MyClientApplication.getUserNum()).undoP) {
                    padUndoStacksList.get(9).undoP.remove(pair);
                }
                for (Pair<Integer, ISketchpadDraw> pair : padUndoStacksList.get(MyClientApplication.getUserNum()).redoP) {
                    padUndoStacksList.get(9).redoP.remove(pair);
                }
                padUndoStacksList.get(MyClientApplication.getUserNum()).clearAllP();
                padUndoStacksList.get(9).raPaintP();

                if (MyClientApplication.isRecording()) {
                    MyClientApplication.setmPathBeanList(new PathBean(new Date().getTime() - MyClientApplication.getStartTime(), AppConfig.PAINT_CLEAR, MyClientApplication.getUserNum()));
                }
            }

        }
    }

    public Bitmap getForeBitmap() {
        return m_bkBitmap;
    }

    public void setBkBitmap(Bitmap bmp) {   //设置背景bitmap
        if (m_bkBitmap != bmp) {
            //m_bkBitmap = bmp;
            m_bkBitmap = BitmapUtil.duplicateBitmap(bmp);
            invalidate();
        }
    }

    public Bitmap getBkBitmap() {
        return m_bkBitmap;
    }

    protected void createStrokeBitmap(int w, int h) {
        m_canvasWidth = w;
        m_canvasHeight = h;
        Bitmap bitmap = Bitmap.createBitmap(m_canvasWidth, m_canvasHeight, Bitmap.Config.ARGB_8888);
        if (null != bitmap) {
            m_foreBitmap = bitmap;
            // Set the fore bitmap to m_canvas to be as canvas of strokes.
            m_canvas.setBitmap(m_foreBitmap);
        }
    }

    protected void setTempForeBitmap(Bitmap tempForeBitmap) {
        if (null != tempForeBitmap) {
            if (null != m_foreBitmap) {
                m_foreBitmap.recycle();
            }
            m_foreBitmap = BitmapCtl.duplicateBitmap(tempForeBitmap);
            if (null != m_foreBitmap && null != m_canvas) {
                m_canvas.setBitmap(m_foreBitmap);
                invalidate();
            }
        }
    }

    protected void setCanvasSize(int width, int height) {//设置画布大小
        if (width > 0 && height > 0) {
            if (m_canvasWidth != width || m_canvasHeight != height) {
                m_canvasWidth = width;
                m_canvasHeight = height;
                createStrokeBitmap(m_canvasWidth, m_canvasHeight);
            }
        }
    }

    //初始化数据   调用
    protected void initialize() {
        m_canvas = new Canvas();//实例画布用于整个绘图操作
        m_bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  //实例化画笔用于bitmap设置画布canvas
        m_undoStack = new SketchPadUndoStack(this, UNDO_SIZE);//实例化队列
        padUndoStacksList = new ArrayList<SketchPadUndoStack>();
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户 1
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户 2
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户3
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户4
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户5
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户6
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户7
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //用户8
        padUndoStacksList.add(new SketchPadUndoStack(this, UNDO_SIZE));  //总栈

    }

    //启动设置画笔的颜色和大小    调用修改
    public void setStrokeType(int type) {
        m_strokeColor = SketchpadView.getStrokeColor();
        m_penSize = SketchpadView.getStrokeSize();
        switch (type) {
            case STROKE_PEN:
                m_curTool = new PenuCtl(m_penSize, m_strokeColor, mContext);
                break;
            case STROKE_ERASER:
                m_curTool = new EraserCtl(m_eraserSize);
                break;
            case STROKE_PLYGON:
                m_curTool = new PlygonCtl(m_penSize, m_strokeColor);
                break;
            case STROKE_RECT:
                m_curTool = new RectuCtl(m_penSize, m_strokeColor, mContext);
                break;
            case STROKE_CIRCLE:
                m_curTool = new Circlectl(m_penSize, m_strokeColor);
                break;
            case STROKE_OVAL:
                m_curTool = new OvaluCtl(m_penSize, m_strokeColor, mContext);
                break;
            case STROKE_LINE:
                m_curTool = new LineCtl(m_penSize, m_strokeColor, mContext);
                break;
            case STROKE_SPRAYGUN:
                m_curTool = new Spraygun(m_penSize, m_strokeColor);
                break;

        }
        //用于记录操作动作名称
        m_strokeType = type;
    }

    /////////////////////////////////////////////////////////////////////
    //构造方法三个 必须的
    public SketchpadView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        initialize();
    }

    public SketchpadView(Context context, AttributeSet attrs) {
        super(context, attrs);
        bgBitmap = ((BitmapDrawable) (getResources().getDrawable(R.drawable.pic1))).getBitmap();
        // TODO Auto-generated constructor stub
        initialize();
    }

    public SketchpadView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
        initialize();
    }

    public void redo() {
        if (padUndoStacksList.get(MyClientApplication.getUserNum()).canRedoP()) {
            int size = padUndoStacksList.get(MyClientApplication.getUserNum()).redoP.size();
            Pair<Integer, ISketchpadDraw> pair = padUndoStacksList.get(MyClientApplication.getUserNum()).redoP.get(size - 1);
            padUndoStacksList.get(9).redoP.remove(pair);
            padUndoStacksList.get(9).undoP.add(pair);
            padUndoStacksList.get(MyClientApplication.getUserNum()).redoP();
        }
        padUndoStacksList.get(9).raPaintP();
        if (MyClientApplication.isRecording()) {
            MyClientApplication.setmPathBeanList(new PathBean(new Date().getTime() - MyClientApplication.getStartTime(), AppConfig.PAINT_REDO, MyClientApplication.getUserNum()));
        }

    }

    public void undo() {

        if (padUndoStacksList.get(MyClientApplication.getUserNum()).canUndoP()) {
            int size = padUndoStacksList.get(MyClientApplication.getUserNum()).undoP.size();
            Pair<Integer, ISketchpadDraw> pair = padUndoStacksList.get(MyClientApplication.getUserNum()).undoP.get(size - 1);
            padUndoStacksList.get(9).redoP.add(pair);
            padUndoStacksList.get(9).undoP.remove(pair);
            padUndoStacksList.get(MyClientApplication.getUserNum()).undoP();
        }
        padUndoStacksList.get(9).raPaintP();
        if (MyClientApplication.isRecording()) {
            MyClientApplication.setmPathBeanList(new PathBean(new Date().getTime() - MyClientApplication.getStartTime(), AppConfig.PAINT_UNDO, MyClientApplication.getUserNum()));
        }

    }

    public void clear() {
        m_canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
        invalidate();
    }

    ///////////////////////////////////////////
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        //canvas.drawBitmap(m_bkBitmap, 0, 0,null);
        //	canvas.drawColor(m_bkColor);
        // Draw background bitmap.
        canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
        if (null != m_bkBitmap) {
            RectF dst = new RectF(getLeft(), getTop(), getRight(), getBottom());
            Rect rst = new Rect(0, 0, m_bkBitmap.getWidth(), m_bkBitmap.getHeight());
            canvas.drawBitmap(m_bkBitmap, rst, dst, m_bitmapPaint);
        }
        if (null != m_foreBitmap) {
            canvas.drawBitmap(m_foreBitmap, 0, 0, m_bitmapPaint);
        }
        if (null != m_curTool) {
            if (STROKE_ERASER != m_strokeType) {
                if (!m_isTouchUp) {   //调用绘图功能
                    m_curTool.draw(canvas);
                }
            }
        }
    }

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // TODO Auto-generated method stub
        super.onSizeChanged(w, h, oldw, oldh);
        if (!m_isSetForeBmp) {
            setCanvasSize(w, h);
        }
        m_canvasWidth = w;
        m_canvasHeight = h;
        m_isSetForeBmp = false;
    }

    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        if (MyClientApplication.isCanDraw())   //判断是否可绘图
        {
            m_isTouchUp = false;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:

                    if (flag == 1) {
                        //seed_fill((int)yx,(int)yy,m_foreBitmap.getPixel((int)yx,(int)yy),m_strokeColor);
                        invalidate();
                        flag = 0;
                    }
                    //根据m_strokeType进行重新生成对象且记录下操作对象

                    setStrokeType(m_strokeType);
                    //将未闭合的多边形闭合
                    m_curTool.touchDown(event.getX(), event.getY());
                    if (STROKE_SPRAYGUN == m_strokeType)  //若当前操作为喷枪则使用线程
                    {
                        myLoop = true;
                    }
                    MyClientApplication.setDrawing(true);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    m_curTool.touchMove(event.getX(), event.getY());
                    //若果当前操作为橡皮擦或喷枪则调用绘图操作
                    if (STROKE_ERASER == m_strokeType) {
                        m_curTool.draw(m_canvas);
                    }
                    if (STROKE_SPRAYGUN == m_strokeType) {
                        m_curTool.draw(m_canvas);
                    }
                    invalidate();
                    m_isDirty = true;
                    m_canClear = true;
                    break;
                case MotionEvent.ACTION_UP:
                    m_isTouchUp = true;
                    if (m_curTool.hasDraw()) {
                        num += 1;
                        padUndoStacksList.get(MyClientApplication.getUserNum()).push(num, m_curTool);
                        padUndoStacksList.get(9).push(num, m_curTool);

                    }
                    m_curTool.touchUp(event.getX(), event.getY());
                    m_curTool.draw(m_canvas);
                    Log.i(".", MyClientApplication.getUserNum() + " : +1");
                    invalidate();
                    m_isDirty = true;
                    m_canClear = true;
                    myLoop = false;
                    MyClientApplication.setDrawing(false);
                    break;
            }
        }
        return true;
    }

    ////////////////////undo栈/////////////////////
    public class SketchPadUndoStack {
        private int m_stackSize = 0;   //栈大小
        private SketchpadView m_sketchPad = null;  //视图对象

        private ArrayList<Pair<Integer, ISketchpadDraw>> undoP = new ArrayList<>();
        private ArrayList<Pair<Integer, ISketchpadDraw>> redoP = new ArrayList<>();
        private ArrayList<Pair<Integer, ISketchpadDraw>> removesP = new ArrayList<>();


        public SketchPadUndoStack(SketchpadView sketchPad, int stackSize) {
            m_sketchPad = sketchPad;
            m_stackSize = stackSize;
        }

        public void push(int i, ISketchpadDraw sketchpadDraw) {
            if (null != sketchpadDraw) {
                undoP.add(new Pair(i, sketchpadDraw));
            }
        }

        public void clearAllP() {
            undoP.clear();
            redoP.clear();
            removesP.clear();
        }


        public void undoP() {
            if (canUndoP() && null != m_sketchPad) {
                Pair<Integer, ISketchpadDraw> pair = undoP.get(undoP.size() - 1);
                redoP.add(pair);
                undoP.remove(pair);
            }
        }


        private void redoP() {
            if (canRedoP() && null != m_sketchPad) {
                Pair<Integer, ISketchpadDraw> pair = redoP.get(redoP.size() - 1);
                undoP.add(pair);
                redoP.remove(redoP.size() - 1);
                m_sketchPad.invalidate();
            }
        }

        public void raPaintP() {
            if (null != m_tempForeBitmap) {
                m_sketchPad.setTempForeBitmap(m_sketchPad.m_tempForeBitmap);
            } else {
                m_sketchPad.createStrokeBitmap(m_sketchPad.m_canvasWidth, m_sketchPad.m_canvasHeight);
            }
            Canvas canvas = m_sketchPad.m_canvas;
            Collections.sort(undoP, new Comparator<Pair<Integer, ISketchpadDraw>>() {
                @Override
                public int compare(Pair<Integer, ISketchpadDraw> p1, Pair<Integer, ISketchpadDraw> p2) {
                    return p1.first - p2.first;
                }
            });
            for (int i = 0; i < undoP.size(); i++) {
                Pair<Integer, ISketchpadDraw> pair = undoP.get(i);
                ISketchpadDraw sketchPadTool = pair.second;
                sketchPadTool.draw(canvas);
            }
            m_sketchPad.invalidate();
        }


        public boolean canUndoP() {
            return (undoP.size() > 0);
        }


        public boolean canRedoP() {
            return (redoP.size() > 0);
        }


    }

}
